Skip to content

Workbench 1.0.0: engine, web UI, CLI, tooling and docs - #4

Merged
mbn-code merged 7 commits into
mainfrom
feat/workbench-v1
Sep 15, 2026
Merged

mbn-code merged 7 commits into
mainfrom
feat/workbench-v1

Conversation

@mbn-code

Copy link
Copy Markdown
Owner

Summary

Takes the workbench from an untagged prototype to 1.0.0: a rewritten execution
engine, a substantially expanded web UI, a full-featured CLI, a quality gate,
CI and a release workflow, and rewritten documentation.

  • Engine: compile cache with in-flight coalescing and LRU eviction,
    structured gcc/clang diagnostics, compiler-flag allowlist, lines/tokens/
    float output checkers with presentation-only detection, Codeforces/AtCoder
    statement parser, atomic whole-workspace problem store with export/import
    and path-traversal validation, Windows support.
  • Web: gutter diagnostics that jump to the line, statement import, per-case
    runs, stress counter-example promotion, checker settings, resizable split,
    keyboard shortcuts, offline-aware API client, full-workspace library.
  • CLI: stress, samples, watch, doctor, clean, version,
    checkers, timeouts and per-sample timing; 57 end-to-end checks.
  • Tooling: make check gate (shellcheck, CLI tests, lint, typecheck, unit
    tests, build, version consistency), GitHub Actions CI on Ubuntu and macOS,
    tag-driven release workflow, LF line endings pinned.
  • Docs: README, CHANGELOG, CONTRIBUTING, SECURITY and the docs/ set
    rewritten for 1.0.0.

Verification

  • make check: shellcheck clean, 57/57 CLI checks, lint and typecheck clean,
    63/63 unit tests, production build, version consistency
  • Playwright: 11/11 specs
  • API smoke-tested against the running dev server

See CHANGELOG.md for the full 1.0.0 entry.

… hardened routes

- cache compiled binaries by compiler/std/flags/source with LRU eviction and
  in-flight coalescing; report cached, diagnostics and rejectedFlags on every
  compile
- parse gcc/clang stderr into structured line/column diagnostics
- add tokens and float checkers next to the lines checker and flag
  presentation-only mismatches
- parse pasted Codeforces/AtCoder statements into samples and limits
  (POST /api/samples)
- validate compiler flags against an allowlist; reject path traversal in
  /api/solution and /api/problem-text; 400 on malformed JSON everywhere
- store: atomic writes, whole-workspace records, duplicate, export/import
- /api/test: checker, epsilon, stopOnFirstFailure, SKIPPED, timing summary
- /api/stress: compilerFlags, checker, seedBase, elapsed and timing stats,
  60s budget
- /api/config: version, compiler version, limits, cache size and reset
- vitest unit suite covering the engine against the real compiler
… full-workspace library

- editor: gutter error/warning markers, clickable diagnostics that jump to
  the line, error/warning counts, cursor status bar, Ctrl+/ comment toggle
- run panel: cached-compile marker, diagnostics list, ignored-flag notice,
  copy and clear, persisted stdin
- tests panel: import samples from a pasted statement, run a single case,
  duplicate, use as stdin, expand/collapse all, stop on first failure,
  whitespace-only hints, SKIPPED verdicts, max time
- stress panel: seed base, timing stats, budget notice, add the failing input
  as a test case or as stdin
- settings: checker mode and epsilon, reset, clear compile cache, server info
- sidebar: whole-workspace save (code, tests, stdin, stress, settings),
  duplicate, filter, relative timestamps, dirty indicator, new workspace,
  export/import; constrain width so long names cannot overflow into the editor
- resizable editor/panel split, remembered tab, Ctrl+1..4 and Ctrl+B
  shortcuts, compiler shown in the header, offline-aware API client
- five new Playwright specs; remove the unused lib/cf.ts and scaffold SVGs
- new commands: stress (solution vs brute.cpp on gen.cpp inputs, saves the
  first counter-example), samples, watch, doctor, clean, version; `new` as
  an alias for template
- template --from dp|graph|math|<file>
- --checker lines|tokens (or CF_CHECKER) on run/test/stress with a hint when
  only whitespace differs; --timeout; per-sample and max timing in cf test
- explicit problem argument wins over the cwd in cf test; brute/gen sources
  are excluded from the solution build; CF_CXX/CXX, NO_COLOR, CF_NO_EDITOR,
  CF_SERVE_PROD; cf update pulls --ff-only
- tests/cli_test.sh: 57 end-to-end checks against the real compiler,
  replacing tests/parser_test.sh and test_full.sh
- scripts/test.sh: report the real exit status (was the negated `if !`
  result), delegate to the CLI suite, shellcheck clean
- scripts/check.sh and `make check`: shellcheck, CLI tests, lint, typecheck,
  unit tests, production build and a CLI/web version-consistency check
- Makefile: check, check-quick, validate and web-* targets; shared source
  resolution for build/run/test/debug
- GitHub Actions CI on Ubuntu and macOS (CLI, web, Playwright) and a release
  workflow that publishes the CHANGELOG section for a pushed v* tag
- .gitattributes pins LF for scripts and C++ sources so Windows checkouts
  run unchanged
…oubleshooting)

- README: CLI and workbench feature overview, quick start for both, updated
  repository map and command table
- docs: every new panel feature, CLI command and option; the compile cache,
  checkers, statement parser, flag allowlist and store in architecture.md;
  every route contract in api.md; quality gates, test suites, CI and the
  release procedure in development.md; new troubleshooting entries for
  ignored flags, the cache, checkers, statement import and Windows
- CHANGELOG.md for 1.0.0; CONTRIBUTING reflects the test layers and gate;
  SECURITY describes the local-only threat model and private reporting
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-15T21:53:29.692085Z ebfc392 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ebfc392c20

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/cf
while IFS= read -r file; do
[ -n "$file" ] && cpp_files+=("$file")
done < <(find "$src_ctx" -maxdepth 1 -name "*.cpp" -type f 2>/dev/null)
collect_cpp_files "$src_ctx"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exclude stress helper mains from normal runs

When a problem contains the documented solution.cpp, brute.cpp, and gen.cpp stress setup, cmd_run passes all three files returned by collect_cpp_files to one compiler invocation. Since each normally defines main, cf and cf <problem> fail with duplicate-symbol linker errors; apply the same helper-file filtering already used by cmd_test_all and cmd_stress.

Useful? React with 👍 / 👎.

Comment thread scripts/cf
started=$(now_ms)
for ((i=0; i<iterations; i++)); do
seed=$((seed_base + i))
if ! "$gen_bin" "$seed" > "$input_tmp" 2>/dev/null; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Apply the timeout to the stress generator

In cmd_stress, the solution and brute are executed through safe_execute, but the generator is invoked directly. A generator that loops or stalls therefore ignores --timeout/CF_TIMEOUT and hangs the entire stress command indefinitely; run it through the same timeout wrapper while preserving the seed argument.

Useful? React with 👍 / 👎.

Comment thread web/app/api/_engine/cpp.ts Outdated
Comment on lines +516 to +517
child.stdout.on("data", (d: Buffer) => {
if (stdout.length >= maxOut) return;
stdout += d.toString("utf8");
if (stdout.length >= maxOut) {
stdout = stdout.slice(0, maxOut);
if (outLen >= maxOut) return;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Detect output overflow at the exact byte cap

If a stdout chunk fills the remaining buffer exactly, the else branch sets outLen to maxOut without marking truncation or killing the child. Every later chunk then returns here immediately, so a runaway writer can continue until the time limit and is reported as an untruncated TLE instead of being stopped at the output cap. The cap check must also handle the case where the accumulated length is already equal to the limit.

Useful? React with 👍 / 👎.

Comment thread web/app/page.tsx
generator: problem.generator || DEFAULT_STRESS.generator,
iterations: stress.iterations,
};
const nextStdin = problem.stdin || problem.tests[0]?.input || "";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve an intentionally empty stdin on load

When a saved workspace deliberately has an empty stdin, loading it replaces that value with the first test case's input because the empty string is treated as missing by ||. This means save/reset/load does not round-trip the workspace state; fallback to the sample should only occur for legacy records where the field is absent, not when it is explicitly empty.

Useful? React with 👍 / 👎.

Comment thread web/app/page.tsx
Comment on lines +390 to +391
code,
tests: toTestCases(tests),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include the imported statement in workspace saves

The new statement-import flow retains only the parsed tests and limits, while this workspace payload still omits statement. After the import dialog clears its local text, saving or exporting the problem therefore stores an empty statement even though the problem model and whole-workspace feature include that field. Keep the pasted statement in page state and include it in the save/load snapshot.

Useful? React with 👍 / 👎.

mbn-code and others added 2 commits September 15, 2026 23:57
…chunks

- include/bits/stdc++.h: only pull in <coroutine> under C++20 (or
  -fcoroutines); libstdc++ 13 rejects it outright with -std=gnu++17, which
  broke the Makefile smoke test and every compile in the web unit tests
- scripts/cf: expand the cleanup and source-file arrays with the
  ${arr[@]+"${arr[@]}"} idiom so an empty array does not trip `set -u` on
  bash 3.2; the EXIT trap made `cf version` exit 1 on macOS
- tests/cli_test.sh: record assertion results with && instead of a bare
  test so a failing check is reported rather than aborting the suite
  silently under `set -e`
- engine: when a stdout/stderr chunk fills the output cap exactly, flag the
  next chunk as truncation and stop the program; macOS delivered a 64 KiB
  chunk that exactly matched the cap and the run was never marked truncated
A side-effect-free `for(;;){}` is undefined behaviour in C++ and gcc 13 at
-O2 on the ubuntu runner deleted it, so the binary returned immediately and
`timedOut` was false. A volatile counter keeps the loop observable on every
compiler.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mbn-code
mbn-code merged commit 0d72925 into main Sep 15, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant